#include "logika.h"
#include "waveformat.h"
#include "waveformatex.h"
#include <QFile>
#include <QDataStream>
#include <QMessageBox>
#include <QDebug>
#include <QPolygonF>
#include <QPointF>
#include <math.h>
Logika::Logika(QObject *parent) :
    QObject(parent)
{
}

void Logika::loadFromFile(const QString &fileName){
////Открою файл.////////////////////////////////////////////////////////////////////////////
	QFile f(fileName);
	f.open(QIODevice::ReadOnly);

////Разберу шапку.////////////////////////////////////////////////////////////////////////////

//====Проверю что в начале есть метка RIFF.==================================================
	QByteArray buff = f.read(4);
	qDebug()<<trUtf8("RIFF %1").arg(buff.data());
	if(buff != "RIFF"){
		QMessageBox::warning(0, trUtf8("Ошибка открытия файла"), trUtf8("Это не файл RIFF"));
		return;
	}

//====Проверю что есть метка WAVE.===========================================================
	f.seek(8);
	buff = f.read(4);
	qDebug()<<trUtf8("WAVE %1").arg(buff.data());
	if(buff != "WAVE"){
		QMessageBox::warning(0, trUtf8("Ошибка открытия файла"), trUtf8("Это не файл WAVE"));
		return;
	}

//====Проверю что есть метка "fmt ".===========================================================
	buff = f.read(4);
	qDebug()<<trUtf8("fmt  %1").arg(buff.data());
	if(buff != "fmt "){
		QMessageBox::warning(0, trUtf8("Ошибка открытия файла"), trUtf8("Нет fmt=чанка"));
		return;
	}

//====Узнаю размер структуры fmt.=======================================================
	buff = f.read(4);
	if(buff.size() != 4){
		QMessageBox::warning(0, trUtf8("Ошибка открытия файла"), trUtf8("Неожиданно закончились данные"));
		return;
	}
	quint32 fmtSize = *((quint32*)(buff.data()));
	qDebug()<<trUtf8("Размер структуры fmt: %1").arg(fmtSize);

//====Прочитаю структуру WaveFormat.==========================================================
	buff = f.read(sizeof(WaveFormat));
	WaveFormat  wf = *((WaveFormat*)(buff.data()));
	F = wf.nSamplesPerSec;

//------Выведу на консоль WaveFormat.----------------------------------------------------------
	qDebug()<<trUtf8("wFormatTag:      %1").arg(wf.wFormatTag);
	qDebug()<<trUtf8("nChannels:       %1").arg(wf.nChannels);
	qDebug()<<trUtf8("nSamplesPerSec:  %1").arg(wf.nSamplesPerSec);
	qDebug()<<trUtf8("nAvgBytesPerSec: %1").arg(wf.nAvgBytesPerSec);
	qDebug()<<trUtf8("nBlockAlign:     %1").arg(wf.nBlockAlign);
	qDebug()<<trUtf8("nBitsPerSample:  %1").arg(wf.nBitsPerSample);

//====Проверю что данные в файле — PCM.==================================================================
	if(wf.wFormatTag != 1){
		QMessageBox::warning(0, trUtf8("Ошибка открытия файла"), trUtf8("Данные в файле не PCM."));
		return;
	}
//====Смещюсь к блоку данных.==================================================================
	if(fmtSize == 16){ // WaveFormat
		qDebug()<<trUtf8("WaveFormat");
	}else if(fmtSize == 18){ // WaveFormatEx
		qDebug()<<trUtf8("WaveFormatEx");
		f.read(2);
	}else{
		qDebug()<<3;
		QMessageBox::warning(0, trUtf8("Ошибка открытия файла"), trUtf8("Неизвестный размер fmt"));
		return;
	}
	f.read(4 + 4);

////Прочитаю данные.////////////////////////////////////////////////////////////////////////////
	if(wf.nChannels == 1){
//====1 канал.===============================================================================
		channels.append(QList<int>());
		while(!f.atEnd()){
			// Привожу тип данных в зависимости от кол-ва бит в сэмпле.
			if(wf.nBitsPerSample == 8){
				channels[0].append( *( (qint8*)( f.read(8).data()) ) );
			}else if(wf.nBitsPerSample == 16){
				channels[0].append( *( (qint16*)( f.read(16).data()) ) );
			}else if(wf.nBitsPerSample == 32){
				channels[0].append( *( (qint32*)( f.read(32).data()) ) );
			}
		}
//===========================================================================================
	}else if(wf.nChannels == 2){
//====2 канала.==================================================================
		channels.append(QList<int>());
		channels.append(QList<int>());
		while(!f.atEnd()){
			// Привожу тип данных в зависимости от кол-ва бит в сэмпле.
			if(wf.nBitsPerSample == 16){
				channels[0].append( *( (qint8*)(f.read(8).data()) ) );
				channels[1].append( *( (qint8*)(f.read(8).data()) ) );
			}else if(wf.nBitsPerSample == 32){
				channels[0].append( *( (qint16*)(f.read(16).data()) ) );
				channels[1].append( *( (qint16*)(f.read(16).data()) ) );
			}
		}
	}
//===========================================================================================

/////////////////////////////////////////////////////////////////////////////////////////////
	emit dataChanged();
}

const QVector< QPointF > Logika::getCurveChannel(int n) const{
	QVector< QPointF > c;
	for(int i = 0; i < channels.at(n).size(); ++i)
		c.append(QPointF(i, channels.at(n).at(i)));
	return c;
}

int Logika::nChannels(){
	return channels.size();
}

QVector< QwtIntervalSample > Logika::getCurveSpectrum(int n) const{
	QVector< QwtIntervalSample > c;
	double a, b, arg, buff = 0, buff2;
	int N =  channels.at(n).size();
	for(int i = 0; i < 100; ++i){
		a = 0;
		b = 0;
		for(int j = 0; j < N; ++j){
			arg = 2 * 3.1411593 * i * j / N;
			a += channels.at(n).at(j) * sin(arg);
			b += channels.at(n).at(j) * cos(arg);
		}
		a /= N;
		b /= N;
		buff2 = F * i / N;
		c.append(QwtIntervalSample(sqrt(a*a + b*b), buff + (buff2 - buff) / 10, buff2));
		buff = buff2;
	}
	return c;
}
